package synchronizeds;

import utils.PrintlnUtils;

/**
 * Java并发——Synchronized关键字和锁升级
 * https://blog.csdn.net/tongdanping/article/details/79647337?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

 * 什么是可见性、原子性、有序性？
 * https://blog.csdn.net/qq_33014341/article/details/127275767

 synchronized和volatile的区别：https://blog.csdn.net/zwb_dzw/article/details/115605133

 1，作用的位置不同
 synchronized是修饰方法，代码块。
 volatile是修饰变量。

 2，作用不同
 synchronized，可以保证变量修改的可见性及原子性，可能会造成线程的阻塞；synchronized在锁释放的时候会将数据写入主内存，保证可见性；
 volatile仅能实现变量修改的可见性，但无法保证原子性，不会造成线程的阻塞；volatile修饰变量后，每次读取都是去主内存进行读取，保证可见性

 synchronized锁的到底是什么？ 8锁问题。
 synchronized修饰普通方法，锁的是方法的调用者，也就是对象。
 synchronized修饰静态方法，锁的是当前类的class对象。
 synchronized修饰代码块，可以设置为锁对象，或者锁引用类型的变量、常量。


 */
public class AccountingSync implements Runnable {
    //共享资源(临界资源)
    static int i = 0;

    /**
     * synchronized 修饰实例方法
     */
    public synchronized void increaseBySync() {
        i++;
    }

    public void increase() {
        i++;
    }


    @Override
    public void run() {
        for (int j = 0; j < 1000_000; j++) {
//            increase();
            increaseBySync();
        }

    }

    public static void main(String[] args) throws InterruptedException {
        AccountingSync accountingSync = new AccountingSync();
        Thread thread1 = new Thread(accountingSync);
        Thread thread2 = new Thread(accountingSync);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();

        //increase 加上synchronized i = 2000000
        //increase 没有 加上synchronized i = 1005579  错误的结果

        //如果increase的synchronized被删除，那么很可能输出结果就会小于2000000，这是因为多个线程同时访问临界资源i

        PrintlnUtils.println("i = "+i);
    }
}
